---
--- 按键控制
---
---@class RedRob.KeyController
local KeyController = RedRob.CreateSingleton("KeyController")
local this = KeyController
function KeyController.OnCreate()
    this.actorId = 0
    this.oldTouchPos = nil
end
function KeyController.OnDestroy()

end
---@return RedRob.Player
function KeyController.GetCtrl()
    return RedRob.ActorManager.GetActor(this.actorId)
end
function KeyController.GetCtrlId()
    return this.actorId
end
function KeyController.SetCtrlId(id)
    this.actorId = id
end
function KeyController.TestAutoFight(dt)
    for k,v in pairs(RedRob.ActorManager.GetActorList()) do
        if(KeyController.IsClickPlayer(v)) then
            return
        end
    end
end
function KeyController.Touched()

    local actor = this.GetCtrl()
    if actor == nil then return end
    if actor:IsDead() then
        return
    end
    if actor:IsInBattle() then
        return
    end
    local pos = Vector3.GetCacheVec():Set(GetMousePosition())

    local hits = RedRob.CameraController.RayCastAll(pos)
    Vector3.ReturnToPool(pos)
    if not hits or hits.Length == 0 then return end
    local clickWPos = nil
    for i = 0,hits.Length-1 do
        local hit = hits[i]
        local hitActor = RedRob.ActorManager.GetClickActor(hit.transform)
        if hitActor  then
            if this.IsClickStone(hitActor) then
                return
            end
            if this.IsClickMineral(hitActor) then
                return
            end
            if this.IsClickPlayer(hitActor) then
                return
            end
        end
        if hit.transform == RedRob.SceneMgr.sceneRoot then
            clickWPos = hit.point
        end
    end
    if clickWPos then
        if RedRob.ClientBattle.SameVector(clickWPos,this.oldTouchPos) then
            return
        end
        this.oldTouchPos = clickWPos
        local battle = RedRob.ClientBattle
        local x,y,z =  battle.WorldToLocal(clickWPos.x,clickWPos.y,clickWPos.z)
        x,y,z = battle.LimitPos(x,y,z)
        actor:CancelAttack()
        actor:MoveToDestination(x,y)
    end
end
---@param hitActor RedRob.Stone
function KeyController.IsClickStone(hitActor)
    if not hitActor then return false end
    local actor = this.GetCtrl()
    local radius = dataTable.getGlobalInt(370)
    if hitActor:IsType(RedRob.Config.ActorType.stone) and not hitActor:IsOpened() then
        if this.IsInRange(actor,hitActor,radius,actor.height/2) then
            RedRob.BattleMsgHandler.ReqAtkStone(hitActor:GetId())
            return true
        end
        actor.ai:PursuitTarget(hitActor,radius,function()
            local p = actor:GetPos()
            local delta = actor.isLeft and -0.0001 or 0.0001
            actor.ai:SendMoveMsg(p.x+delta,p.y)
            RedRob.BattleMsgHandler.ReqAtkStone(hitActor:GetId())
        end,true)
        return true
    end
    return false
end
---@param hitActor RedRob.Minerals
function KeyController.IsClickMineral(hitActor)
    if not hitActor then return false end
    local actor = this.GetCtrl()
    local radius = dataTable.getGlobalInt(370)
    if  hitActor:IsType(RedRob.Config.ActorType.minerals) and not hitActor:IsOpened() then
        if this.IsInRange(actor,hitActor,radius) then
            RedRob.BattleMsgHandler.ReqGather(hitActor:GetId())
            return true
        end
        actor.ai:PursuitTarget(hitActor,radius,function()
            local p = actor:GetPos()
            local delta = actor.isLeft and -0.0001 or 0.0001
            actor.ai:SendMoveMsg(p.x+delta,p.y)
            RedRob.BattleMsgHandler.ReqGather(hitActor:GetId())
        end)
        return true
    end
    return false
end
---@param hitActor RedRob.Player
function KeyController.IsClickPlayer(hitActor)
    if not hitActor then return false end
    local actor = this.GetCtrl()
    if hitActor == actor then
        return false
    end
    local radius = dataTable.getGlobalInt(370)
    if hitActor:IsType(RedRob.Config.ActorType.player) and not hitActor:IsDead() and not hitActor:IsInBattle() then
        if hitActor:IsUnSelectState() then
            return false
        end
        if this.IsInRange(actor,hitActor,radius) then
            local p = actor:GetPos()
            if RedRob.ClientBattle.IsFightStart() then
                RedRob.BattleMsgHandler.ReqPk(hitActor:GetId(),p.x,p.y)
                return true
            end
        else
            actor.ai:PursuitTarget(hitActor,radius,function()
                local p = actor:GetPos()
                local delta = actor.isLeft and -0.0001 or 0.0001
                actor.ai:SendMoveMsg(p.x + delta,p.y)
                if RedRob.ClientBattle.IsFightStart() then
                    RedRob.BattleMsgHandler.ReqPk(hitActor:GetId(),p.x,p.y)
                end
            end)
            return true
        end
    end
    return false
end
---@param hitActor RedRob.Pawn
function KeyController.IsInRange(actor,hitActor,radius,height)
    if height == nil then height = 0 end
    local p1 = Vector3.GetCacheVec():SetV(actor:GetPos())
    p1.y = p1.y + height
    local p2 = hitActor:GetPos()
    if Vector3.SqrDistance(p1,p2) <= radius * radius then
        Vector3.ReturnToPool(p1)
        return true
    end
    Vector3.ReturnToPool(p1)
    return false
end

